package com.ys.code.generator.core;

import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.taskdefs.condition.Http;
import org.springframework.stereotype.Service;

import com.ys.code.generator.core.jdbc.ColumnField;
import com.ys.code.generator.core.jdbc.FileList;
import com.ys.code.generator.core.jdbc.JdbcTypeNameTranslator;
import com.ys.code.generator.core.vo.BaseInfo;
import com.ys.code.generator.core.vo.ParamVo;
import com.ys.code.generator.core.vo.SimpleVo;
import com.ys.code.generator.util.DateUtil;
import com.ys.code.generator.util.FileUtil;
import com.ys.code.generator.util.JdbcUtil;
import com.ys.code.generator.util.ServiceConnectType;
import com.ys.code.generator.util.TemplateUtil;
import com.ys.tdm.bean.code.DataBase;
import com.ys.tdm.controller.code.CompactAlgorithm;
import com.ys.tdm.service.code.IDataBaseService;

@Service
public class MyCodeGenerator {
	
	@Resource
	private IDataBaseService dataBaseService;
	@Resource
	private TemplateUtil templateUtil;
	
	public static void main(String[] args) throws Exception {
		MyCodeGenerator cg = new MyCodeGenerator();
//		cg.generate();
	}

	private String getField(String column) {
		String[] columnSplit = column.split("_");

		StringBuffer field = new StringBuffer();

		for (int i = 0; i < columnSplit.length; ++i)
			if (i != 0) {
				field.append(StringUtils.capitalize(StringUtils.lowerCase(columnSplit[i])));
			} else {
				field.append(StringUtils.uncapitalize(StringUtils.lowerCase(columnSplit[i])));
			}

		return field.toString();
	}

	public List<BaseInfo> getBaseInfoList(ParamVo params) throws Exception {
		List<BaseInfo> baseInfoList = new ArrayList<BaseInfo>();
		//TODO 查询数据库连接表得到相关的配置
		DataBase dataBaseById = new DataBase();
		if (StringUtils.isNotBlank(params.getDbUrlId())) {
			dataBaseById = dataBaseService.getDataBaseById(params.getDbUrlId());
		}
		String[] drivers = new String[]{dataBaseById.getDriverName()};
		String baseUrl = ServiceConnectType.getConnectType(dataBaseById.getDriverName(),dataBaseById.getServiceIp(),dataBaseById.getPort()).toString();
		String[] urls = new String[]{baseUrl+"/"+params.getDbName()};
		String[] userNames = new String[]{dataBaseById.getDbUser()};
		String[] passwords = new String[]{dataBaseById.getDbPwd()};

		String[] tableNames = params.getTableNames();
		String[] primaryKeys = params.getPrimaryKeys();
		String[] authors = params.getAuthors();
		String[] companyNames = params.getCompanyNames();
		String[] projectNames = params.getProjectNames();
		String[] models = params.getModels();
		String[] objectNameCns = params.getObjectNameCns();
		String[] objectNames = params.getObjectNames();
		String[] fLowerObjectNames = params.getfLowerObjectNames();
				 // 可以不填
		String[] abbObjectNames = params.getAbbObjectNames();

		String[] parameters = params.getParameters();
		String[] templates = params.getTemplates();

		if (null != drivers) {
			if (null != tableNames) {
				for (int i = 0; i < tableNames.length; i++) {
					BaseInfo baseInfo = new BaseInfo();
					if (1 == drivers.length) {
						baseInfo.setDriver(drivers[0].trim());
						baseInfo.setUrl(urls[0].trim());
						baseInfo.setUserName(userNames[0].trim());
						baseInfo.setPassword(passwords[0].trim());
					} else {
						baseInfo.setDriver(StringUtils.isNotBlank(drivers[i]) ? drivers[i].trim() : drivers[0].trim());
						baseInfo.setUrl(StringUtils.isNotBlank(urls[i]) ? urls[i].trim() : urls[0].trim());
						baseInfo.setUserName(
								StringUtils.isNotBlank(userNames[i]) ? userNames[i].trim() : userNames[0].trim());
						baseInfo.setPassword(
								StringUtils.isNotBlank(passwords[i]) ? passwords[i].trim() : passwords[0].trim());
					}
					baseInfo.setTableName(tableNames[i].trim());
					if (null != primaryKeys && primaryKeys.length > 0) {
						baseInfo.setPrimaryKeyMerger(primaryKeys[i].trim());
					}
					if (1 == authors.length) {
						baseInfo.setAuthor(authors[0].trim());
					} else {
						baseInfo.setAuthor(StringUtils.isNotBlank(authors[i]) ? authors[i].trim() : authors[0].trim());
					}

					if (1 == companyNames.length) {
						baseInfo.setCompanyName(companyNames[0].trim());
					} else {
						baseInfo.setCompanyName(StringUtils.isNotBlank(companyNames[i]) ? companyNames[i].trim()
								: companyNames[0].trim());
					}

					if (1 == projectNames.length) {
						baseInfo.setProjectName(projectNames[0].trim());
					} else {
						baseInfo.setProjectName(StringUtils.isNotBlank(projectNames[i]) ? projectNames[i].trim()
								: projectNames[0].trim());
					}

					if (1 == models.length) {
						baseInfo.setModel(models[0].trim());
					} else {
						baseInfo.setModel(StringUtils.isNotBlank(models[i]) ? models[i].trim() : models[0].trim());
					}

					baseInfo.setObjectNameCn(objectNameCns[i].trim());
					baseInfo.setObjectName(objectNames[i].trim());
					if (null != fLowerObjectNames && fLowerObjectNames.length > 0) {
						baseInfo.setfLowerObjectName(fLowerObjectNames[i].trim());
					}
					baseInfo.setAbbObjectName(abbObjectNames[i].trim());

					// 设置自定义的参数和自定义的模板
					if (!ArrayUtils.isEmpty(parameters) && parameters.length > i
							&& StringUtils.isNotBlank(parameters[i])) {
						baseInfo.setParameters(this.getMapInfo(parameters[i].trim()));
					}
					if (!ArrayUtils.isEmpty(templates) && templates.length > i
							&& StringUtils.isNotBlank(templates[i])) {
						baseInfo.setTemplates(this.getMapInfo(templates[i].trim()));
					}

					baseInfoList.add(baseInfo);
				}
			}
		}

		return this.getBaseInfoList(baseInfoList);
	}

	// 拆分数据封装到map中去
	private Map<String, String> getMapInfo(String paras) {
		Map<String, String> map = null;
		if (StringUtils.isNotBlank(paras)) {
			String[] ps = paras.split("\\$");
			if (!ArrayUtils.isEmpty(ps)) {
				map = new HashMap<String, String>();
				for (String str : ps) {
					if (StringUtils.isNotBlank(str)) {
						String[] array = str.trim().split("\\^");
						if (!ArrayUtils.isEmpty(array) && array.length == 2) {
							map.put(array[0].trim(), array[1].trim());
						}
					}
				}
			}
		}
		return map;
	}

	public List<BaseInfo> getBaseInfoList(List<BaseInfo> baseInfoList) throws Exception {
		Connection connection = null;
		try {
			for (BaseInfo baseInfo : baseInfoList) {
				String driver = baseInfo.getDriver();
				String url = baseInfo.getUrl();
				String userName = baseInfo.getUserName();
				String password = baseInfo.getPassword();
				String tableName = baseInfo.getTableName();

				connection = JdbcUtil.getConnection(driver, url, userName, password);
				Statement statement = connection.createStatement();

				ResultSet rs = statement.executeQuery("select * from " + tableName + " where 1=2");

				Map<String, String> columnCommentMap = getColumnComment(connection, tableName);

				ResultSetMetaData rsmd = rs.getMetaData();

				List<ColumnField> columnFieldList = new ArrayList<ColumnField>();

				int count = rsmd.getColumnCount();

				for (int i = 1; i <= count; ++i) {
					String columnName = rsmd.getColumnName(i);
					int jdbcType = rsmd.getColumnType(i);
					ColumnField columnField = new ColumnField();
					String field = getField(columnName);
					String cField = StringUtils.capitalize(field);

					columnField.setColumn(columnName);
					columnField.setField(field);
					columnField.setcField(cField);
					columnField.setJdbcType(JdbcTypeNameTranslator.getJdbcTypeName(jdbcType));
					columnField.setJavaType(JdbcTypeNameTranslator.getJavaType(jdbcType));
					columnField.setComment((String) columnCommentMap.get(columnName));

					columnFieldList.add(columnField);
				}
				baseInfo.setColumnFieldList(columnFieldList);
				baseInfo.setCreateTime(DateUtil.DateToString(new Date(), "yyyy-MM-dd HH:mm:ss"));

				// 取得主键信息
				DatabaseMetaData dbMeta = connection.getMetaData();
				ResultSet primaryKeys = dbMeta.getPrimaryKeys(null, null, tableName);
				StringBuffer primaryKeysSbf = new StringBuffer();

				List<String> primaryKeysList = new ArrayList<String>();
				int i = 0;
				while (primaryKeys.next()) {
					System.err.println("****** Comment ******");
					System.err.println("[数据库名]TABLE_CAT : " + primaryKeys.getObject(1));
					System.err.println("[]TABLE_SCHEM: " + primaryKeys.getObject(2));
					System.err.println("[表名称]TABLE_NAME : " + primaryKeys.getObject(3));
					System.err.println("[主键名称]COLUMN_NAME: " + primaryKeys.getObject(4));
					System.err.println("[主键的顺序位置]KEY_SEQ : " + primaryKeys.getObject(5));
					System.err.println("[]PK_NAME : " + primaryKeys.getObject(6));
					System.err.println("****** ******* ******");
					primaryKeysList.add((String) primaryKeys.getObject(4));
					i++;
					primaryKeysSbf.append(primaryKeys.getObject(4)).append(",");
				}

				System.err.println(primaryKeysSbf.toString());
				System.err.println(this.setPrimaryKeysFromArray(primaryKeysSbf.toString().split(","), baseInfo));

				baseInfo.setPrimaryKeys(primaryKeysList.toArray(new String[primaryKeysList.size()]));
				String st = this.setPrimaryKeysFromArray(primaryKeysSbf.toString().split(","), baseInfo);
				if (StringUtils.isBlank(baseInfo.getPrimaryKeyMerger())) {
					baseInfo.setPrimaryKeyMerger(st);
				} else {
					System.err.println(baseInfo.getPrimaryKeyMerger());
				}

			}
		} catch (Exception e) {
		} finally {
			if (connection != null) {
				connection.close();
			}
			// throw localObject;

			if (connection == null)
				return baseInfoList;
		}
		connection.close();

		label358: return baseInfoList;
	}

	/** 组合主键：如果file_id,property_value_id为共同主键，那么组合后的结果为FileIdAndPropertyValueId */
	public String setPrimaryKeysFromArray(String[] strs, BaseInfo baseInfo) { // 数据库中列名的命名规则：如file_id,property_value_id等等，使用“_”分割
		if (null != strs && strs.length > 0) {
			String[] primaryKeysConvert = new String[strs.length];
			StringBuffer sbkeys = new StringBuffer();
			int i = 0;
			for (String str : strs) { // 循环主键
				if (str.indexOf("_") != -1) {
					StringBuffer sbkey = new StringBuffer();
					for (String string : str.split("_")) {
						sbkey.append(StringUtils.capitalize(string.trim())); // 首字母大写
					}
					sbkeys.append(sbkey);
					primaryKeysConvert[i] = StringUtils.uncapitalize(sbkey.toString());
				} else {
					sbkeys.append(StringUtils.capitalize(str.trim()));// 首字母大写
					primaryKeysConvert[i] = StringUtils.uncapitalize(str.trim()); // 首字母小写
				}

				i++;
				if (i < strs.length) {
					sbkeys.append("And");
				}
			}
			baseInfo.setPrimaryKeysConvert(primaryKeysConvert);
			return StringUtils.isNotBlank(sbkeys.toString()) ? sbkeys.toString().trim() : null;

		}
		return null;
	}

	public Map<String, String> getColumnComment(Connection connection, String tableName) throws Exception {
		Map<String, String> map = new HashMap<String, String>();

		Statement statement = connection.createStatement();

		String sql = "SELECT column_name,COLUMN_COMMENT FROM information_schema.COLUMNS WHERE table_name =";
		ResultSet rs = statement.executeQuery(sql + "UPPER('" + tableName + "')");

		if (rs.next()) {
			rs.previous();
		} else {
			rs = statement.executeQuery(sql + "'" + tableName + "'");
		}

		while (rs.next()) {
			String column = rs.getString(1);
			String comments = rs.getString(2);
			map.put(column, comments);
		}

		return map;
	}

	public SimpleVo<String>  generate(ParamVo params,String  basePath) throws Exception {
		SimpleVo<String> vo = new SimpleVo<String>("101", "生成失败");
		List<BaseInfo> datas = getBaseInfoList(params);
		Random rand = new Random();
		String num = rand.nextInt(100) + 1 + "";
		String zipName = datas.get(0).getProjectName() + num;
		File file = new File(basePath);
		List<String> filePaths = new ArrayList<String>();
		for (BaseInfo baseInfo : datas) {
			Map<String, String> map = FileList.getFileToPath(baseInfo);
			baseInfo.setPrimaryKeyMergerFLower(StringUtils.uncapitalize(baseInfo.getPrimaryKeyMerger())); // 主键合并后首字母小写
			for (Iterator<Entry<String, String>> localIterator = map.entrySet().iterator(); localIterator.hasNext();) {
				Map.Entry entry = (Map.Entry) localIterator.next();
				String context = templateUtil.getText((String) entry.getKey(), baseInfo); // 生成模版
				String filePath = basePath+"\\codePackage" + File.separator + ((String) entry.getValue());
				FileUtil.string2File(context, filePath);
				filePaths.add(filePath);
			}
		}
		boolean flag = CompactAlgorithm.createZipUtil(basePath+"\\zipPackage\\"+zipName+".zip",basePath+"\\codePackage");
		//boolean flag = FileUtil.createCardImgZip(basePath, zipName);
		
		if(flag) {
			vo = new SimpleVo<String>("100",zipName);
			//filePaths.add(basePath +File.separator+ zipName);
			//vo.setDatas(filePaths);
		}
		return vo;
	}
}